//
//  Array+ZJ.swift
//  ZJSwiftKit
//
//  Created by zyx on 2023/2/17.
//

import Foundation

/// 遵循了Equatable协议协议
public protocol ZJEquatableArray: ZJSinglePrefixProtocal where ZJT: Equatable { }

/// Extend Array with `zj` proxy.
extension Array: ZJSinglePrefixProtocal {
    public typealias ZJT = Element
}

/// 数组去遵循这个协议
extension Array: ZJEquatableArray where ZJT: Equatable { }

/// 扩展了遵循初始化协议的数组
extension ZJSinglePrefix where Base: ExpressibleByArrayLiteral & ZJSinglePrefixProtocal {
    
    /// 转JSON字符串
    /// - Parameter opt: 用于写入JSON数据的选项。 默认为 []
    /// - Returns: jsonString maybe return ""
    public func toJsonString(options opt: JSONSerialization.WritingOptions = []) -> String {
        
        if (!JSONSerialization.isValidJSONObject(base)) {
            print("无法解析出JSONString")
            return ""
        }
        if let data = try? JSONSerialization.data(withJSONObject: base, options: opt),
           let JSONString =  String.init(data: data, encoding: .utf8){
            return JSONString
        }
        return ""
    }
    
    /// 自定义下标写法，安全取值，越界返回nil 用法:[1, 2, 3, 4, 5].zj[safe: 3]
    /// subscript用于更方便的访问集合中的数据
    /// indices.contains用于判断索引值是否在区间内
    /// - Parameter index: 索引值
    public subscript(safe index: Int) -> ZJT? {
        if let array = base as? [ZJT] {
            if array.indices.contains(index) {
                return array[index]
            }else{
                return nil
            }
        }
        return nil
    }
}

extension ZJSinglePrefix where Base == Array<ZJT> {
    /// 获取数组中的指定元素的索引值，适用于数组元素类型不都相同
    /// - Parameter item: 元素
    /// - Returns: 索引值数组
    public func indexes<T>(of item: T) -> [Int] where T: Equatable {
        var indexes = [Int]()
        for index in 0..<base.count {
            if let compare = base[index] as? T {
                if compare == item {
                    indexes.append(index)
                }
            }
        }
        return indexes
    }
    
    public func makeElement(_ excute: (ZJT) -> ()) {
        for element in base {
            excute(element)
        }
    }
    
    public func makeElements(_ excute: (ZJT, inout Bool) -> ()) {
        var stop: Bool = false
        for element in base {
            excute(element, &stop)
            if stop {
                break
            }
        }
    }
}

/// 扩展遵循了ZJEquatableArray协议的数组
extension ZJSinglePrefix where Base: ZJEquatableArray {
    
    /// 获取数组中的指定元素的索引值，适用于数组元素类型相同
    /// - Parameter item: 元素
    /// - Returns: 索引值数组
    public func indexes(of item: Base.ZJT) -> [Int] {
        var indexes = [Int]()
        if let array = base as? [Base.ZJT] {
            for index in 0..<array.count where array[index] == item {
                indexes.append(index)
            }
        }
        return indexes
    }
    
}
